package org.example.security.filter;

import org.example.security.autoconfiguration.SecurityProperties;
import org.example.security.entity.User;
import org.example.security.util.JwtTokenUtil;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * jwt登录授权过滤器
 * @author zuoyi
 */
public class DefaultJwtAuthenticationTokenFilter extends JwtAuthenticationTokenFilter {

    private JwtTokenUtil jwtTokenUtil;
    private SecurityProperties securityProperties;

    public DefaultJwtAuthenticationTokenFilter(SecurityProperties securityProperties,JwtTokenUtil jwtTokenUtil) {
        this.securityProperties = securityProperties;
        this.jwtTokenUtil = jwtTokenUtil;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader(securityProperties.getJwt().getAuthorizationHeaderName());
        // 判断token是否有效
        boolean flag = jwtTokenUtil.validateToken(token);
        if (flag) {
            // token有效， 判断系统有没有当前用户的登录状态
            if (null == SecurityContextHolder.getContext().getAuthentication()) {
                // 无登录状态，从token中获取登录用户信息
                User userInfoFromToken = jwtTokenUtil.getUserInfoFromToken(token);
                UserDetails userDetails = new UserDetails() {
                    @Override
                    public Collection<? extends GrantedAuthority> getAuthorities() {
                        List<SimpleGrantedAuthority> collect = userInfoFromToken.getPermissions().stream().map(item -> {
                            return new SimpleGrantedAuthority(item);
                        }).collect(Collectors.toList());
                        return collect;
                    }

                    @Override
                    public String getPassword() {
                        return null;
                    }

                    @Override
                    public String getUsername() {
                        return userInfoFromToken.getUsername();
                    }

                    @Override
                    public boolean isAccountNonExpired() {
                        return true;
                    }

                    @Override
                    public boolean isAccountNonLocked() {
                        return true;
                    }

                    @Override
                    public boolean isCredentialsNonExpired() {
                        return true;
                    }

                    @Override
                    public boolean isEnabled() {
                        return true;
                    }
                };
                // 向系统注册登录状态
                UsernamePasswordAuthenticationToken authenticationToken =
                        new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                // 刷新token并设置到响应头中
                if (jwtTokenUtil.canRefresh(token)) {
                    String refreshToken = jwtTokenUtil.refreshToken(token);
                    response.setHeader("refresh_token",refreshToken);
                }
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            }
        }
        filterChain.doFilter(request, response);
    }
}
